﻿//========================================================= 
/**@file H003Installer.h
 * @brief H003应用装载器
 * 
 * @date 2017-07-13   10:01:31
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_H003INSTALLER_H_
#define _LIBZHOUYB_H003INSTALLER_H_
//--------------------------------------------------------- 
#include "../H002/H002Installer.h"

#include "../module/TC_FingerCmdDriver.h"
#include "../module/WE_FingerCmdDriver.h"
#include "../module/WltDecoderCmdDriver.h"

#include "../module/LC_FileCipherFactoryCmdDriver.h"
#include "../module/LC_CipherCmdDriver.h"

#include "H003AppJsonCmdDriver.h"

#include "../../lc/lc_lib.h"
#include "../../pboc/pboc_app.h"
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace driver {
//--------------------------------------------------------- 
/// H003应用装载器
class H003Installer : public H002Installer
{
public:
    H003Installer() : H002Installer() {}
    H003Installer(CommandRunner& runner) : H002Installer(runner) {}

    void Install(const char* devId = NULL)
    {
        H002Installer::Install(devId, false);

        // 新增加指纹仪
        const char FINGER_GATE[] = "FINGER_GATE";
        H002Installer::InstallNEW<TC_FingerCmdDriver>("TC", FINGER_GATE);
        H002Installer::InstallNEW<WE_FingerCmdDriver>("WE", FINGER_GATE);

        const char APP_GATE[] = "APP_GATE";
        H002Installer::NewGate(APP_GATE, "1B 24 5A", devId);
        H002Installer::InstallNEW<H003AppJsonCmdDriver>("APP", APP_GATE);
    }
    void InstallCipher(const char* devId = NULL)
    {
        if(_runner.IsNull())
            return;

        const char CIPHER_KEY[] = "Cipher";
        const char CIPHER_FACTORY_KEY[] = "CipherFactory";

        CommandInstaller::RegisteNew<LC_CipherCmdDriver>(*_runner, CIPHER_KEY);
        CommandInstaller::RegisteNew<LC_FileCipherFactoryCmdDriver>(_runner, CIPHER_FACTORY_KEY);

        CommandSetter setter(_runner);
        CommandSetter cipherSetter = _runner->Get(CIPHER_KEY);
        Ref<CommandScriptActuator> bindCmd;
        StringArguments callArg;
        StringArguments arg;
        // IsCipherMode
        Ref<ComplexCommand> timeoutMsCmd = _runner->LookUp("SetTimeoutMS");
        Ref<ComplexCommand> complexCmd = _runner->LookUp("Cipher.IsCipherMode");
        complexCmd->Clear();
        arg.Clear();
        arg.Put("Timeout", "200");
        arg.Put("Send", "1B 24 5A");
        bindCmd = NewScriptCMD(CIPHER_KEY);
        bindCmd->Run(timeoutMsCmd, arg).ToArg().Import(true)
            .Run(cipherSetter.LookUp("IsCipherMode"), arg).Export(true)
            .Run(timeoutMsCmd, ComplexCommand::RunOnAlways);
        complexCmd->Bind(bindCmd->ScriptCmd());
        // Script.IsCipherMode
        bindCmd = NewScriptCMD(CIPHER_KEY);
        bindCmd->Run(timeoutMsCmd, arg).ToArg()
            .Run(cipherSetter.LookUp("Write"), arg)
            .Run(timeoutMsCmd, ComplexCommand::RunOnAlways);
        Ref<ComplexCommand> isCipherModeCmd = bindCmd->ScriptCmd("IsCipherMode");
        // Cipher.SwitchToCipher
        complexCmd = _runner->LookUp("Select_IInteractiveTrans");
        bindCmd = NewScriptCMD(CIPHER_KEY);
        _BindCMD(bindCmd, CIPHER_KEY, "", "Write;Read;IInteractiveTrans");
        bindCmd->Run(cipherSetter.LookUp("IInteractiveTrans")).ToArg().Run(complexCmd);
        arg.Clear();
        callArg.Clear();
        callArg.Put("IsEncrypt", "true");
        H003AppJsonCmdDriver::MakeCall("JNI", "Setting", callArg, arg);
        Ref<ComplexCommand> appOnCallCmd = _runner->Get("APP").LookUp("OnCall");
        _runner->Registe("Cipher.SwitchToCipher")->Bind(isCipherModeCmd)
            .Bind(appOnCallCmd, arg, ComplexCommand::RunOnFailed).Bind(bindCmd->ScriptCmd());
        // Cipher.Exit
        bindCmd = NewScriptCMD(CIPHER_KEY);
        CommandSetter editorSetter = _GetAutoCMD();
        CommandRunnerCmdEditor<ArgParser>::RebindCMD(editorSetter, bindCmd, "Write", "DEV.Write");
        CommandRunnerCmdEditor<ArgParser>::RebindCMD(editorSetter, bindCmd, "Read", "DEV.Read");
        CommandRunnerCmdEditor<ArgParser>::RebindCMD(editorSetter, bindCmd, "IInteractiveTrans", "DEV.IInteractiveTrans");
        bindCmd->Run(setter.LookUp("DEV.IInteractiveTrans")).ToArg().Run(complexCmd);
        arg.Clear();
        callArg.Clear();
        callArg.Put("IsEncrypt", "false");
        H003AppJsonCmdDriver::MakeCall("JNI", "Setting", callArg, arg);
        Ref<ComplexCommand> exitCipherCmd = bindCmd->Registe(isCipherModeCmd);
        exitCipherCmd->Bind(bindCmd->MakeCmd(appOnCallCmd, arg))
            .Bind(bindCmd->ScriptCmd());
        _runner->Registe("Cipher.Exit")->Bind(exitCipherCmd).Bind(_MakeCMDF(CommandScript, SuccessRET), ComplexCommand::RunOnFailed);
        // Select_IBaseDevice
        complexCmd = _runner->Registe("Select_IBaseDevice");
        complexCmd->Bind(cipherSetter.LookUp("SelectDevice"), ComplexCommand::RunOnAlways);
        
        CommandRunnerActuator actuator(*_runner);
        actuator.Run("IInteractiveTrans", true).Set(CIPHER_KEY).Run("SelectDevice").Reset();
        actuator.Set(CIPHER_FACTORY_KEY).Run("ICipherFactory", true).Set(CIPHER_KEY).Arg("LrcSize", 4).Run("UpdateCipher").Reset();
        actuator.Set(CIPHER_KEY).Arg("AckMode", 0).Arg("MIN", 0x01).Arg("MAX", 0x0F).Run("RangeMode").Reset();

        _runner->LastErr().MoveTo("IInteractiveTrans").Add(CIPHER_KEY);
        _runner->ResetErr();
    }
};
//--------------------------------------------------------- 
} // nemespace driver
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_H003INSTALLER_H_
//========================================================= 